package com.ruoyi.common.utils;


import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import java.io.ByteArrayInputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description: xml相关工具
 * @author: Ly
 * @create: 2025-01-19 14:36
 **/
public class XmlUtils {
//    protected static final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 从节点中查找标签对应节点
     * @param node
     * @param label
     * @return
     */
    public static Node getXmlLabelNode(Node node, String label) {
        Node labelNode = null;
        if (node !=null) {
            // 通过标签名获取system-id节点的值
            labelNode = node.getFirstChild();
            while (labelNode != null && !label.equalsIgnoreCase(labelNode.getNodeName())) {
                labelNode = labelNode.getNextSibling();
            }
            return labelNode;
        }
        return labelNode;
    }

    /**
     * 从节点中查找标签对应值
     * @param node
     * @param label
     * @return
     */
    public static String getXmlLabelValue(Node node, String label) {
        if (node == null) {
            return null;
        }
        String value = null;
        // 通过标签名获取system-id节点的值
        Node labelNode = node.getFirstChild();
        while (labelNode!= null &&!label.equalsIgnoreCase(labelNode.getNodeName())) {
            labelNode = labelNode.getNextSibling();
        }
        if (labelNode!= null) {
//                        System.out.println(labelNode+":" + systemIdNode.getTextContent());
            value = labelNode.getTextContent();
        }
        return value;
    }

    /*public List<String> findNetConfXmlNodes(String xml, String nodePath) {
        List<String> list = new ArrayList<>();*/
    public static NodeList findNetConfXmlNodes(String xml, String nodePath) {
//        List<String> list = new ArrayList<>();
        NodeList nl = null;
        try {
            // 将字符串转换为InputStream
            ByteArrayInputStream input = new ByteArrayInputStream(xml.toString().getBytes("UTF-8"));

            // 创建DocumentBuilderFactory对象
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 创建DocumentBuilder对象
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 解析输入流获取Document对象
            Document document = builder.parse(input);

            // 创建XPathFactory对象
            XPathFactory xPathfactory = XPathFactory.newInstance();
            // 创建XPath对象
            XPath xpath = xPathfactory.newXPath();
            // 编译XPath表达式
            XPathExpression expr = xpath.compile(nodePath);

            // 执行XPath表达式，获取结果
            nl = (NodeList) expr.evaluate(document, XPathConstants.NODESET);

            /*// 遍历结果
            for (int i = 0; i < nl.getLength(); i++) {
                System.out.println(nl.item(i).getTextContent());
                list.add(nl.item(i).getTextContent());
            }*/
        } catch (Exception e) {
            System.out.println("获取xml节点失败");
//            logger.error("获取xml节点失败", e);
        }
        return nl;
    }
    /**
     * 获取XML指定节点内容
     * @param xml xml内容
     * @param attrName 节点名称（例如：TranData.OutputData.Result）
     * @return
     * @throws Exception
     */
    public static String getXmlAttrValue(String xml,String attrName) throws Exception {
        if (null==xml||xml.equals("")||null==attrName||attrName.equals("")){
            return null;
        }
        String[] attrs = attrName.split("\\.");
        int length = attrs.length;
        String result = null;
// 将xml格式字符串转化为DOM对象
        org.dom4j.Document document = DocumentHelper.parseText(xml);
// 获取根结点对象
        Element element = document.getRootElement();
        List<Element> elements = Arrays.asList(element);
        for (int i = 0; i < length; i++) {
            Map<String,Element> elementMap = elements.stream().collect(Collectors.toMap(e->e.getName(), e->e));
            if (elementMap.containsKey(attrs[i])){
                if (i==length-1){
                    result = elementMap.get(attrs[i]).asXML();
                    break;
                }else {
                    elements = elementMap.get(attrs[i]).elements();
                }
            }else {
                throw new Exception("Node does not exist:"+attrName);
            }
        }
        return result;
    }
    public static void main(String[] args) throws Exception {
        String xml = "<rpc-reply\n" +
                "    xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"\n" +
                "    xmlns:if=\"http://fiberhome.com/fhnw/yang/interface/fos-interface-common\"\n" +
                "    xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\"\n" +
                "    xmlns:ncx=\"http://netconfcentral.org/ns/yuma-ncx\" message-id=\"163\">\n" +
                "    <rpc-error>\n" +
                "        <error-type>application</error-type>\n" +
                "        <error-tag>operation-failed</error-tag>\n" +
                "        <error-severity>error</error-severity>\n" +
                "        <error-app-tag>general-error</error-app-tag>\n" +
                "        <error-path>if/interfaces/interface</error-path>\n" +
                "        <error-message xml:lang=\"en\">Error:The interface has other configurations. Please clear them first. </error-message>\n" +
                "        <error-info>\n" +
                "            <error-number>907</error-number>\n" +
                "            <error-service>ifmgr(830005:if_l3_intf )</error-service>\n" +
                "            <error-reason>Error:The interface has other configurations. Please clear them first. </error-reason>\n" +
                "            <error-detail>Operation failed, 0x83000514 returned from Service function. Run service function error. (classid=0x830005) (key_info=[ifName:loopback 1023 ])</error-detail>\n" +
                "        </error-info>\n" +
                "    </rpc-error>\n" +
                "</rpc-reply>";
        String result = getXmlAttrValue(xml,"rpc-reply.rpc-error.error-message");
        System.out.println(result);
    }
}
